package com.kingsoft.dc.khaos

import java.io.IOException
import java.util.concurrent.ConcurrentHashMap

import com.kingsoft.dc.khaos.util.{KhaosConstants, KhaosUtils, Logging}
import org.scalatest.ConfigMap

import scala.collection.{Map, mutable}
import scala.collection.JavaConverters._

/**
  * Created by chengguangqing on 2019/5/27.
  */
class KhaosConf extends Logging {

    val settings = new ConcurrentHashMap[String, String]()

    var propertiesFile: String = null

    lazy val defaultKhaosProperties: mutable.HashMap[String, String] = {
      val defaultProperties = new mutable.HashMap[String, String]()
      if (propertiesFile != null) {
        propertiesFile.split(",", -1).toList.foreach { fileName =>
          KhaosUtils.getPropertiesFromFile(fileName).foreach { case (k, v) =>
            defaultProperties(k) = v
          }
        }
      }
      defaultProperties
    }


    //初始化加载
    mergeDefaultKhaosProperties()

    private def mergeDefaultKhaosProperties(): Unit = {
    propertiesFile = Option(propertiesFile).getOrElse(KhaosUtils.getDefaultPropertiesFile(sys.env))
      defaultKhaosProperties.foreach { case (k, v) =>
      if (!settings.contains(k)) {
        settings.put(k, v)
      }
    }

    // 20200903 加载默认配置文件
    var propMap: Map[String, String] = Map[String,String]()
    try{
      propMap = KhaosUtils.loadDefaultConf(KhaosConstants.KHAOS_DEFAULT_CONF)
    } catch {
      case e: Exception => {
        //不抛异常, 调用配置方如果未取到配置,可以使用默认配置
        log.error(s"khaos loadDefaultConf fail: ${KhaosConstants.KHAOS_DEFAULT_CONF}",e)
      }
    }
    propMap.foreach { case (k, v) =>
      if (!settings.contains(k)) {
        settings.put(k, v)
      }
    }
  }

    /**
      * 设置应用程序的名称，用于web UI的展示
      */
    def setAppName(name: String): KhaosConf = {
      set("khaos.app.name", name)
    }

    /**
      * 设置应用程序的各种配置信息
      */
    def set(key: String, value: String): KhaosConf = {
      if (key == null) {
        throw new NullPointerException("null key")
      }
      if (value == null) {
        throw new NullPointerException(s"null value for ${key}")
      }
      settings.put(key, value)
      this
    }


    /**
     * 设置应用程序的各种配置信息
     */
    def setAll(configMap: Map[String, String ]):KhaosConf = {
      for ((key, value) <- configMap){
        if (key == null) {
          throw new NullPointerException("null key")
        }
        if (value == null) {
          throw new NullPointerException(s"null value for ${key}")
        }
        settings.put(key,value)
      }
      log.info(s"setting:${settings}")
      this
    }

    /**
     * 设置应用程序的各种配置信息
     */
    def remove(key: String): KhaosConf = {
      if (key == null) {
        throw new NullPointerException("null key")
      }
      settings.remove(key)
      this
    }

    /**
      * 获取配置文件信息
      */
    def getOption(key: String): Option[String] = {
      Option(settings.get(key))
    }

    /**
      * 获取配置文件信息，返回类型为double，若key不存在，则返回指定的默认值
      */
    def getInt(key: String, defaultValue: Int): Int = {
      getOption(key).map(_.toInt).getOrElse(defaultValue)
    }

  /**
    * 获取配置文件信息，返回类型为double，若key不存在，则返回指定的默认值
    */
  def getInt(key: String): Int = {
    getOption(key).map(_.toInt).get
  }

  /**
      * 获取配置文件信息，返回类型为double，若key不存在，则返回指定的默认值
      */
    def getDouble(key: String, defaultValue: Double): Double = {
      getOption(key).map(_.toDouble).getOrElse(defaultValue)
    }

    /**
      * 获取配置文件信息，返回类型为String，若key不存在，则返回指定的默认值
      */
    def getString(key: String, defaultValue: String): String = {
      getOption(key).map(_.toString).getOrElse(defaultValue)
    }

    /**
      * 获取配置文件信息，返回类型为String
      */
    def getString(key: String): String = {
      getOption(key).map(_.toString).get
    }


    /**
      * 获取配置文件信息，返回类型为Boolean，若key不存在，则返回指定的默认值
      */
    def getBoolean(key: String, defaultValue: Boolean): Boolean = {
      getOption(key).map(_.toBoolean).getOrElse(defaultValue)
    }

    /**
      * 判断配置文件信息是否包含指定的key，返回类型为Boolean
      */
    def contains(key: String): Boolean = settings.containsKey(key)

    /**
      * 获取配置文件信息,以列表形式返回所有配置信息
      */
    def getAll: Seq[(String, String)] = {
      settings.entrySet().asScala.map(x => (x.getKey, x.getValue)).toSeq
    }

    /**
      * 使用key前缀匹配配置信息,并携带前缀返回
      */
    def getAllWithPrefix(prefix: String): Seq[(String, String)] = {
      getAll.filter { case (k, v) => k.startsWith(prefix) }
    }

    /**
      * 使用key前缀匹配配置信息,删除前缀后返回
      */
    def getAllWithUnPrefix(prefix: String): Seq[(String, String)] = {
      getAll.filter { case (k, v) => k.startsWith(prefix) }
          .map { case (k, v) => (k.substring(prefix.length), v) }
    }


    def validateSettings() = {}

}
